#ifndef LOG_H
#define LOG_H

#include <iostream>
#include <spdlog/spdlog.h>
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/async.h"

#define LDEBUG(...) common_lib::SpdLog::Instance()->GetLogger()->debug(__VA_ARGS__)
#define LINFO(...) common_lib::SpdLog::Instance()->GetLogger()->info(__VA_ARGS__)
#define LWARNING(...) common_lib::SpdLog::Instance()->GetLogger()->warn(__VA_ARGS__)
#define LERROR(...) common_lib::SpdLog::Instance()->GetLogger()->error(__VA_ARGS__)
#define LCritical(...) common_lib::SpdLog::Instance()->GetLogger()->critical(__VA_ARGS__)

#define FDebug(...) common_lib::SpdLog::Instance()->FaultDebug(__VA_ARGS__)
#define FInfo(...) common_lib::SpdLog::Instance()->FaultInfo(__VA_ARGS__)
#define FWarn(...) common_lib::SpdLog::Instance()->FaultWarn(__VA_ARGS__)
#define FError(...) common_lib::SpdLog::Instance()->FaultError(__VA_ARGS__)
#define FCritical(...) common_lib::SpdLog::Instance()->FaultCritical(__VA_ARGS__)

namespace common_lib
{
    enum LOG_TYPE
    {
        BASIC = 0,
        DAILY,
        ROTATING
    };

    class SpdLog
    {
    public: 
        static SpdLog *Instance();
        void InitSpdLog(std::string path, std::string node_name);
        void EndLog();
        void SetLevel(int level);
        std::shared_ptr<spdlog::logger> GetLogger()
        {
            return ptr_logger_;
        };
        void Init();
        void SetType(LOG_TYPE type);
        void SetLogSize(float size, float num);

        inline void FaultDebug(std::string user_name, std::string fault, std::string fault_code, std::string fault_src)
        {
            common_lib::SpdLog::Instance()->GetLogger()->debug("[" + user_name + "]:" + "{},{},{}", fault, fault_code, fault_src);
        }
        inline void FaultInfo(std::string user_name, std::string fault, std::string fault_code, std::string fault_src)
        {
            common_lib::SpdLog::Instance()->GetLogger()->info("[" + user_name + "]:" + "{},{},{}", fault, fault_code, fault_src);
        }
        inline void FaultWarn(std::string user_name, std::string fault, std::string fault_code, std::string fault_src)
        {
            common_lib::SpdLog::Instance()->GetLogger()->warn("[" + user_name + "]:" + "{},{},{}", fault, fault_code, fault_src);
        }
        inline void FaultError(std::string user_name, std::string fault, std::string fault_code, std::string fault_src)
        {
            common_lib::SpdLog::Instance()->GetLogger()->error("[" + user_name + "]:" + "{},{},{}", fault, fault_code, fault_src);
        }
        inline void FaultCritical(std::string user_name, std::string fault, std::string fault_code, std::string fault_src)
        {
            common_lib::SpdLog::Instance()->GetLogger()->critical("[" + user_name + "]:" + "{},{},{}", fault, fault_code, fault_src);
        }

        inline void DataDebug(std::string describe)
        {
            common_lib::SpdLog::Instance()->GetLogger()->debug(":" + describe);
        }
        inline void DataInfo(std::string describe)
        {
            common_lib::SpdLog::Instance()->GetLogger()->info(":" + describe);
        }
        inline void DataError(std::string describe)
        {
            common_lib::SpdLog::Instance()->GetLogger()->error(":" + describe);
        }
        inline void DataWarn(std::string describe)
        {
            common_lib::SpdLog::Instance()->GetLogger()->warn(":" + describe);
        }
        inline void DataCritical(std::string describe)
        {
            common_lib::SpdLog::Instance()->GetLogger()->critical(":" + describe);
        }
    
    private:
        //私有构造函数，拷贝构造函数和拷贝赋值函数，禁止在类外声明实例
        SpdLog();
        ~SpdLog();
        SpdLog(const SpdLog &other) = delete;
        SpdLog &operator=(const SpdLog &other) = delete;

    private:
        std::shared_ptr<spdlog::logger> ptr_logger_;
        static pthread_mutex_t mutex;
        static SpdLog *unique_instance;
        float rotating_type_log_size_;
        float rotation_type_log_num_;
        int log_level_;
        LOG_TYPE type_;

        std::string GenerateFileName(std::string path, std::string node_name);
        time_t logger_create_time;   //日志创建时间
    };
};

#endif